home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / popserv.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  16KB  |  767 lines

  1. /* POP Server state machine - see RFC 937
  2.  *
  3.  *  also see other credits in popcli.c
  4.  *  10/89 Mike Stockett wa7dyx
  5.  *  Modified 5/27/90 by Allen Gwinn, N5CKP, for later NOS releases.
  6.  *  Added to NOS by PA0GRI 2/6/90 (and linted into "standard" C)
  7.  *
  8.  *  ATARI Version by David Nash - dnash@chaos.demon.co.uk
  9.  */
  10.  
  11. #include <stdio.h>
  12. #include <time.h>
  13. #include <sys/stat.h>
  14. #ifdef UNIX
  15. #include <sys/types.h>
  16. #endif
  17. #if    defined(__STDC__) || defined(__TURBOC__)
  18. #include <stdarg.h>
  19. #endif
  20. #include <ctype.h>
  21. #include <setjmp.h>
  22. #include "global.h"
  23. #include "mbuf.h"
  24. #include "cmdparse.h"
  25. #include "socket.h"
  26. #include "proc.h"
  27. #include "files.h"
  28. #include "pop.h"
  29.  
  30. extern char Nospace[];
  31.  
  32. /* Prototypes for functions defined in popserv.c */
  33. int pop1(int argc,
  34.          char **argv,
  35.          void *p);
  36. int pop0(int argc,
  37.          char **argv,
  38.          void *p);
  39. static void __stdargs popserv(int s,
  40.                     void *unused,
  41.                     void *p);
  42. static struct pop_scb *create_scb(void);
  43. static void delete_scb(register struct pop_scb *scb);
  44. void rrip(register char *s);
  45. void pop_sm(struct pop_scb *scb);
  46. void do_cleanup(struct pop_scb *scb);
  47. void state_error(struct pop_scb *scb,
  48.                  char *msg);
  49. void close_folder(struct pop_scb *scb);
  50. void open_folder(struct pop_scb *scb);
  51. void read_message(struct pop_scb *scb);
  52. void retrieve_message(struct pop_scb *scb);
  53. void get_message(struct pop_scb *scb,
  54.                  int msg_no);
  55. static int poplogin(char *username,
  56.                     char *pass);
  57. int isdeleted(struct pop_scb *scb,
  58.               int msg_no);
  59. void deletemsg(struct pop_scb *scb,
  60.                int msg_no);
  61. int newmail(struct pop_scb *scb);
  62. void print_message_length(struct pop_scb *scb);
  63.  
  64. static struct pop_scb *create_scb __ARGS((void));
  65. static void delete_scb __ARGS((struct pop_scb *scb));
  66. static void __stdargs popserv __ARGS((int s,void *unused,void *p));
  67. static int poplogin __ARGS((char *pass,char *username));
  68.  
  69. /* I don't know why this isn't static, it isn't called anywhere else {was} */
  70. void pop_sm __ARGS((struct pop_scb *scb));
  71.  
  72. static int Spop = -1; /* prototype socket for service */
  73.  
  74. /* Start up POP receiver service */
  75. int
  76. pop1(argc,argv,p)
  77.  
  78. int argc;
  79. char *argv[];
  80. void *p;
  81.  
  82. {
  83.     struct sockaddr_in lsocket;
  84.     int s;
  85.  
  86.     if (Spop != -1) {
  87.         return 0;
  88.     }
  89.  
  90.     psignal(Curproc,0);        /* Don't keep the parser waiting */
  91.     chname(Curproc,"POP listener");
  92.  
  93.     lsocket.sin_family = AF_INET;
  94.     lsocket.sin_addr.s_addr = INADDR_ANY;
  95.     if(argc < 2)
  96.         lsocket.sin_port = IPPORT_POP;
  97.     else
  98.         lsocket.sin_port = atoi(argv[1]);
  99.  
  100.     Spop = socket(AF_INET,SOCK_STREAM,0);
  101.  
  102.     bind(Spop,(char *)&lsocket,sizeof(lsocket));
  103.  
  104.     listen(Spop,1);
  105.  
  106.     for (;;) {
  107.         if((s = accept(Spop,NULLCHAR,(int *)NULL)) == -1)
  108.             break;    /* Service is shutting down */
  109.  
  110.         /* Spawn a server */
  111.  
  112.         newproc("POP server",2048,popserv,s,NULL,NULL,0);
  113.     }
  114.     return 0;
  115. }
  116.  
  117. /* Shutdown POP service (existing connections are allowed to finish) */
  118.  
  119. int
  120. pop0(argc,argv,p)
  121. int argc;
  122. char *argv[];
  123. void *p;
  124.  
  125. {
  126.     close_s(Spop);
  127.     Spop = -1;
  128.     return 0;
  129. }
  130.  
  131. static void
  132. __stdargs popserv(s,unused,p)
  133. int s;
  134. void *unused;
  135. void *p;
  136. {
  137.     struct pop_scb *scb;
  138.  
  139.     sockowner(s,Curproc);        /* We own it now */
  140.     log(s,"open POP");
  141.  
  142.     if((scb = create_scb()) == NULLSCB) {
  143.         tprintf(Nospace);
  144.         log(s,"close POP - no space");
  145.         close_s(s);
  146.         return;
  147.     }
  148.  
  149.     scb->socket = s;
  150.     scb->state  = AUTH;
  151.  
  152.     (void) usprintf(s,greeting_msg,Hostname);
  153.  
  154. loop:    if ((scb->count = recvline(s,scb->buf,BUF_LEN)) == -1){
  155.         /* He closed on us */
  156.  
  157.         goto quit;
  158.     }
  159.  
  160.     rip(scb->buf);
  161.     if (strlen(scb->buf) == 0)        /* Ignore blank cmd lines */
  162.         goto loop;
  163.     pop_sm(scb);
  164.     if (scb->state == DONE)
  165.         goto quit;
  166.  
  167.     goto loop;
  168.  
  169. quit:
  170.     log(scb->socket,"close POP");
  171.     close_s(scb->socket);
  172.     delete_scb(scb);
  173. }
  174.  
  175.  
  176. /* Create control block, initialize */
  177.  
  178. static struct
  179. pop_scb *create_scb()
  180. {
  181.     register struct pop_scb *scb;
  182.  
  183.     if((scb = (struct pop_scb *)callocw(1,sizeof (struct pop_scb))) == NULLSCB)
  184.         return NULLSCB;
  185.  
  186.     scb->username[0] = '\0';
  187.     scb->msg_status = NULL;
  188.     scb->wf = NULL;
  189.  
  190.     scb->count = scb->folder_file_size = scb->msg_num = 0;
  191.  
  192.     scb->folder_modified = FALSE;
  193.     return scb;
  194. }
  195.  
  196.  
  197. /* Free resources, delete control block */
  198.  
  199. static void
  200. delete_scb(scb)
  201. register struct pop_scb *scb;
  202. {
  203.  
  204.     if (scb == NULLSCB)
  205.         return;
  206.     if (scb->wf != NULL)
  207.         fclose(scb->wf);
  208.     if (scb->msg_status  != NULL)
  209.         free((char *)scb->msg_status);
  210.  
  211.     free((char *)scb);
  212. }
  213.  
  214. /* replace terminating end of line marker(s) (\r and \n) with null */
  215. void
  216. rrip(s)
  217. register char *s;
  218. {
  219.     register char *cp;
  220.  
  221.     if((cp = strchr(s,'\r')) != NULLCHAR)
  222.         *cp = '\0';
  223.     if((cp = strchr(s,'\n')) != NULLCHAR)
  224.         *cp = '\0';
  225. }
  226.  
  227. /* --------------------- start of POP server code ------------------------ */
  228.  
  229. #define    BITS_PER_WORD        16
  230.  
  231. #define isSOM(x)        ((strncmp(x,"From ",5) == 0))
  232.  
  233. /* Command string specifications */
  234.  
  235. static char    ackd_cmd[] = "ACKD",
  236.         acks_cmd[] = "ACKS",
  237. #ifdef POP_FOLDERS
  238.         fold_cmd[] = "FOLD ",
  239. #endif
  240.         login_cmd[] = "HELO ",
  241.         nack_cmd[] = "NACK",
  242.         quit_cmd[] = "QUIT",
  243.         read_cmd[] = "READ",
  244.         retr_cmd[] = "RETR";
  245.  
  246. void
  247. pop_sm(scb)
  248. struct pop_scb *scb;
  249. {
  250.     char password[40];
  251. #ifndef ATARI
  252.     void state_error(struct pop_scb *,char *);
  253.     void open_folder(struct pop_scb *);
  254.     void do_cleanup(struct pop_scb *);
  255.     void read_message(struct pop_scb *);
  256.     void retrieve_message(struct pop_scb *);
  257.     void deletemsg(struct pop_scb *,int);
  258.     void get_message(struct pop_scb *,int);
  259.     void print_message_length(struct pop_scb *);
  260. /*    void close_folder(struct pop_scb *); */
  261. #endif
  262. #ifdef POP_FOLDERS
  263.     void select_folder(struct pop_scb *);
  264. #endif
  265.  
  266.     if (scb == NULLSCB)    /* be certain it is good -- wa6smn */
  267.         return;
  268.  
  269.     switch(scb->state) {
  270.     case AUTH:
  271.         if (strncmp(scb->buf,login_cmd,strlen(login_cmd)) == 0){
  272.             sscanf(scb->buf,"HELO %s%s",scb->username,password);
  273.  
  274.             if (!poplogin(scb->username,password)) {
  275.                 log(scb->socket,"POP access DENIED to %s",
  276.                         scb->username);
  277.                 state_error(scb,"Access DENIED!!");
  278.                 return;
  279.             }
  280.  
  281.             log(scb->socket,"POP access granted to %s",
  282.                     scb->username);
  283.             open_folder(scb);
  284.         } else if (strncmp(scb->buf,quit_cmd,strlen(quit_cmd)) == 0){
  285.             do_cleanup(scb);
  286.         } else
  287.             state_error(scb,"(AUTH) Expected HELO or QUIT command");
  288.         break;
  289.  
  290.     case MBOX:
  291.         if (strncmp(scb->buf,read_cmd,strlen(read_cmd)) == 0)
  292.             read_message(scb);
  293.  
  294. #ifdef POP_FOLDERS
  295.         else if (strncmp(scb->buf,fold_cmd,strlen(fold_cmd)) == 0)
  296.             select_folder(scb);
  297.  
  298. #endif
  299.  
  300.         else if (strncmp(scb->buf,quit_cmd,strlen(quit_cmd)) == 0) {
  301.             do_cleanup(scb);
  302.         } else
  303.             state_error(scb,
  304. #ifdef POP_FOLDERS
  305.                     "(MBOX) Expected FOLD, READ, or QUIT command");
  306. #else
  307.                     "(MBOX) Expected READ or QUIT command");
  308. #endif
  309.         break;
  310.  
  311.     case ITEM:
  312.         if (strncmp(scb->buf,read_cmd,strlen(read_cmd)) == 0)
  313.             read_message(scb);
  314.  
  315. #ifdef POP_FOLDERS
  316.  
  317.         else if (strncmp(scb->buf,fold_cmd,strlen(fold_cmd)) == 0)
  318.             select_folder(scb);
  319. #endif
  320.  
  321.         else if (strncmp(scb->buf,retr_cmd,strlen(retr_cmd)) == 0)
  322.             retrieve_message(scb);
  323.         else if (strncmp(scb->buf,quit_cmd,strlen(quit_cmd)) == 0)
  324.             do_cleanup(scb);
  325.         else
  326.             state_error(scb,
  327. #ifdef POP_FOLDERS
  328.                "(ITEM) Expected FOLD, READ, RETR, or QUIT command");
  329. #else
  330.                "(ITEM) Expected READ, RETR, or QUIT command");
  331. #endif
  332.         break;
  333.  
  334.     case NEXT:
  335.         if (strncmp(scb->buf,ackd_cmd,strlen(ackd_cmd)) == 0){
  336.                 /* ACKD processing */
  337.             deletemsg(scb,scb->msg_num);
  338.             scb->msg_num++;
  339.             get_message(scb,scb->msg_num);
  340.         } else if (strncmp(scb->buf,acks_cmd,strlen(acks_cmd)) == 0){
  341.                 /* ACKS processing */
  342.             scb->msg_num++;
  343.             get_message(scb,scb->msg_num);
  344.         } else if (strncmp(scb->buf,nack_cmd,strlen(nack_cmd)) == 0){
  345.                 /* NACK processing */
  346.             fseek(scb->wf,scb->curpos,SEEK_SET);
  347.         } else {
  348.             state_error(scb,"(NEXT) Expected ACKD, ACKS, or NACK command");
  349.             return;
  350.         }
  351.  
  352.         print_message_length(scb);
  353.         scb->state  = ITEM;
  354.         break;
  355.  
  356.     case DONE:
  357.         do_cleanup(scb);
  358.         break;
  359.  
  360.     default:
  361.         state_error(scb,"(TOP) State Error!!");
  362.         break;
  363.     }
  364. }
  365.  
  366. void
  367. do_cleanup(scb)
  368. struct pop_scb *scb;
  369. {
  370. #ifndef ATARI    
  371.     void close_folder(struct pop_scb *);
  372. #endif
  373.  
  374.     close_folder(scb);
  375.     (void) usprintf(scb->socket,signoff_msg);
  376.     scb->state = DONE;
  377. }
  378.  
  379. void
  380. state_error(scb,msg)
  381. struct pop_scb *scb;
  382. char *msg;
  383. {
  384.     (void) usprintf(scb->socket,error_rsp,msg);
  385.     scb->state = DONE;
  386. }
  387.  
  388. #ifdef POP_FOLDERS
  389.  
  390. select_folder(scb)
  391. struct pop_scb    *scb;
  392. {
  393.     sscanf(scb->buf,"FOLD %s",scb->username);
  394.  
  395.     if (scb->wf != NULL)
  396.         close_folder(scb);
  397.  
  398.     open_folder(scb);
  399. }
  400.  
  401. #endif
  402.  
  403.  
  404. void
  405. close_folder(scb)
  406. struct pop_scb *scb;
  407. {
  408.     char folder_pathname[64];
  409.     char line[BUF_LEN];
  410.     FILE *fd;
  411.     int deleted = FALSE;
  412.     int msg_no = 0;
  413.     struct stat folder_stat;
  414. #ifndef ATARI    
  415.     int newmail(struct pop_scb *);
  416.     int isdeleted(struct pop_scb *,int);
  417. #endif    
  418.  
  419.     if (scb->wf == NULL)
  420.         return;
  421.  
  422.     if (!scb->folder_modified) {
  423.         /* no need to re-write the folder if we have not modified it */
  424.  
  425.         fclose(scb->wf);
  426.         scb->wf = NULL;
  427.  
  428.         free((char *)scb->msg_status);
  429.         scb->msg_status = NULL;
  430.         return;
  431.     }
  432.  
  433.  
  434.     sprintf(folder_pathname,"%s/%s.txt",Mailspool,scb->username);
  435.  
  436.     if (newmail(scb)) {
  437.         /* copy new mail into the work file and save the
  438.            message count for later */
  439.  
  440.         if ((fd = fopen(folder_pathname,"r")) == NULL) {
  441.             state_error(scb,"Unable to add new mail to folder");
  442.             return;
  443.         }
  444.  
  445.         fseek(scb->wf,0,SEEK_END);
  446.         fseek(fd,scb->folder_file_size,SEEK_SET);
  447.         while (!feof(fd)) {
  448.             fgets(line,BUF_LEN,fd);
  449.             fputs(line,scb->wf);
  450.         }
  451.  
  452.         fclose(fd);
  453.     }
  454.  
  455.     /* now create the updated mail folder */
  456.  
  457.     if ((fd = fopen(folder_pathname,"w")) == NULL){
  458.         state_error(scb,"Unable to update mail folder");
  459.         return;
  460.     }
  461.  
  462.     rewind(scb->wf);
  463.     while (!feof(scb->wf)){
  464.         fgets(line,BUF_LEN,scb->wf);
  465.  
  466.         if (isSOM(line)){
  467.             msg_no++;
  468.             if (msg_no <= scb->folder_len)
  469.                 deleted = isdeleted(scb,msg_no);
  470.             else
  471.                 deleted = FALSE;
  472.         }
  473.  
  474.         if (deleted)
  475.             continue;
  476.  
  477.         fputs(line,fd);
  478.     }
  479.  
  480.     fclose(fd);
  481.  
  482.     /* trash the updated mail folder if it is empty */
  483.  
  484.     if ((stat(folder_pathname,&folder_stat) == 0) && (folder_stat.st_size == 0))
  485.         unlink(folder_pathname);
  486.  
  487.     fclose(scb->wf);
  488.     scb->wf = NULL;
  489.  
  490.     free((char *)scb->msg_status);
  491.     scb->msg_status = NULL;
  492. }
  493.  
  494. void
  495. open_folder(scb)
  496. struct pop_scb    *scb;
  497. {
  498.     char folder_pathname[64];
  499.     char line[BUF_LEN];
  500.     FILE *fd;
  501. #ifndef ATARI
  502.     FILE *tmpfile();
  503. #endif    
  504.     struct stat folder_stat;
  505.  
  506.  
  507.     sprintf(folder_pathname,"%s/%s.txt",Mailspool,scb->username);
  508.     scb->folder_len       = 0;
  509.     scb->folder_file_size = 0;
  510.     if (stat(folder_pathname,&folder_stat)){
  511.          (void) usprintf(scb->socket,no_mail_rsp);
  512.          return;
  513.     }
  514.  
  515.     scb->folder_file_size = folder_stat.st_size;
  516.     if ((fd = fopen(folder_pathname,"r")) == NULL){
  517.         state_error(scb,"Unable to open mail folder");
  518.         return;
  519.     }
  520.  
  521.     if ((scb->wf = tmpfile()) == NULL) {
  522.         state_error(scb,"Unable to create work folder");
  523.         return;
  524.     }
  525.  
  526.     while(!feof(fd)) {
  527.         fgets(line,BUF_LEN,fd);
  528.  
  529.         /* scan for begining of a message */
  530.  
  531.         if (isSOM(line))
  532.             scb->folder_len++;
  533.  
  534.         /* now put  the line in the work file */
  535.  
  536.         fputs(line,scb->wf);
  537.     }
  538.  
  539.     fclose(fd);
  540.  
  541.     scb->msg_status_size = (scb->folder_len) / BITS_PER_WORD;
  542.  
  543.     if ((((scb->folder_len) % BITS_PER_WORD) != 0) ||
  544.         (scb->msg_status_size == 0))
  545.         scb->msg_status_size++;
  546.  
  547.     if ((scb->msg_status = (unsigned int *) callocw(scb->msg_status_size,
  548.                 sizeof(unsigned int))) == NULL) {
  549.         state_error(scb,"Unable to create message status array");
  550.         return;
  551.     }
  552.  
  553.     (void) usprintf(scb->socket,count_rsp,scb->folder_len);
  554.  
  555.     scb->state  = MBOX;
  556. }
  557.  
  558. void
  559. read_message(scb)
  560. struct pop_scb    *scb;
  561. {
  562. #ifndef ATARI    
  563.     void get_message(struct pop_scb *,int);
  564.     void print_message_length(struct pop_scb *);
  565. #endif
  566.  
  567.     if (scb == NULLSCB)    /* check for null -- wa6smn */
  568.         return;
  569.     if (scb->buf[sizeof(read_cmd) - 1] == ' ')
  570.         scb->msg_num = atoi(&(scb->buf[sizeof(read_cmd) - 1]));
  571.     else
  572.         scb->msg_num++;
  573.  
  574.     get_message(scb,scb->msg_num);
  575.     print_message_length(scb);
  576.     scb->state  = ITEM;
  577. }
  578.  
  579. void
  580. retrieve_message(scb)
  581. struct pop_scb    *scb;
  582. {
  583.     char line[BUF_LEN];
  584.     long cnt;
  585.     void rrip(char *);
  586.  
  587.     if (scb == NULLSCB)    /* check for null -- wa6smn */
  588.         return;
  589.     if (scb->msg_len == 0) {
  590.         state_error(scb,"Attempt to access a DELETED message!");
  591.         return;
  592.     }
  593.  
  594.     cnt  = scb->msg_len;
  595.     while(!feof(scb->wf) && (cnt > 0)) {
  596.         fgets(line,BUF_LEN,scb->wf);
  597.         rrip(line);
  598.  
  599.         (void) usprintf(scb->socket,msg_line,line);
  600.         cnt -= (strlen(line)+2);    /* Compensate for CRLF */
  601.     }
  602.  
  603.     scb->state = NEXT;
  604. }
  605.  
  606. void
  607. get_message(scb,msg_no)
  608. struct pop_scb    *scb;
  609. int msg_no;
  610. {
  611.     char line[BUF_LEN];
  612. /*    long ftell(); */
  613.     void rrip(char *);
  614.  
  615.     if (scb == NULLSCB)    /* check for null -- wa6smn */
  616.         return;
  617.     scb->msg_len = 0;
  618.     if (msg_no > scb->folder_len) {
  619.         scb->curpos  = 0;
  620.         scb->nextpos = 0;
  621.         return;
  622.     } else {
  623.         /* find the message and its length */
  624.  
  625.         rewind(scb->wf);
  626.         while (!feof(scb->wf) && (msg_no > -1)) {
  627.             if (msg_no > 0)
  628.                 scb->curpos = ftell(scb->wf);
  629.             
  630.             fgets(line,BUF_LEN,scb->wf);
  631.             rrip(line);
  632.  
  633.             if (isSOM(line))
  634.                 msg_no--;
  635.  
  636.             if (msg_no != 0)
  637.                 continue;
  638.  
  639.             scb->nextpos  = ftell(scb->wf);
  640.             scb->msg_len += (strlen(line)+2);    /* Add CRLF */
  641.         }
  642.     }
  643.  
  644.     if (scb->msg_len > 0)
  645.         fseek(scb->wf,scb->curpos,SEEK_SET);
  646.  
  647.     /* we need the pointers even if the message was deleted */
  648.  
  649.     if  (isdeleted(scb,scb->msg_num))
  650.         scb->msg_len = 0;
  651. }
  652.  
  653. static int
  654. poplogin(username,pass)
  655. char *pass;
  656. char *username;
  657. {
  658.     char buf[80];
  659.     char *cp;
  660.     char *cp1;
  661.     FILE *fp;
  662.  
  663.     if((fp = fopen(Popusers,"r")) == NULLFILE) {
  664.         /* User file doesn't exist */
  665.         tprintf("POP users file %s not found\n",Popusers);
  666.         return(FALSE);
  667.     }
  668.  
  669.     while(fgets(buf,sizeof(buf),fp),!feof(fp)) {
  670.         if(buf[0] == '#')
  671.             continue;    /* Comment */
  672.  
  673.         if((cp = strchr(buf,':')) == NULLCHAR)
  674.             /* Bogus entry */
  675.             continue;
  676.  
  677.         *cp++ = '\0';        /* Now points to password */
  678.         if(strcmp(username,buf) == 0)
  679.             break;        /* Found user name */
  680.     }
  681.  
  682.     if(feof(fp)) {
  683.         /* User name not found in file */
  684.  
  685.         fclose(fp);
  686.         return(FALSE);
  687.     }
  688.     fclose(fp);
  689.  
  690.     if ((cp1 = strchr(cp,':')) == NULLCHAR)
  691.         return(FALSE);
  692.  
  693.     *cp1 = '\0';
  694.     if(strcmp(cp,pass) != 0) {
  695.         /* Password required, but wrong one given */
  696.  
  697.         return(FALSE);
  698.     }
  699.  
  700.     /* whew! finally made it!! */
  701.  
  702.     return(TRUE);
  703. }
  704.  
  705. int
  706. isdeleted(scb,msg_no)
  707. struct pop_scb *scb;
  708. int msg_no;
  709. {
  710.     unsigned int mask = 1,offset;
  711.  
  712.     msg_no--;
  713.     offset = msg_no / BITS_PER_WORD;
  714.     mask <<= msg_no % BITS_PER_WORD;
  715.     return (((scb->msg_status[offset]) & mask)? TRUE:FALSE);
  716. }
  717.  
  718. void
  719. deletemsg(scb,msg_no)
  720. struct pop_scb *scb;
  721. int msg_no;
  722. {
  723.     unsigned int mask = 1,offset;
  724.  
  725.     if (scb == NULLSCB)    /* check for null -- wa6smn */
  726.         return;
  727.     msg_no--;
  728.     offset = msg_no / BITS_PER_WORD;
  729.     mask <<= msg_no % BITS_PER_WORD;
  730.     scb->msg_status[offset] |= mask;
  731.     scb->folder_modified = TRUE;
  732. }
  733.  
  734. int
  735. newmail(scb)
  736. struct pop_scb *scb;
  737. {
  738.     char folder_pathname[64];
  739.     struct stat folder_stat;
  740.  
  741.     sprintf(folder_pathname,"%s/%s.txt",Mailspool,scb->username);
  742.  
  743.     if (stat(folder_pathname,&folder_stat)) {
  744.         state_error(scb,"Unable to get old mail folder's status");
  745.         return(FALSE);
  746.     } else
  747.         return ((folder_stat.st_size > scb->folder_file_size)? TRUE:FALSE);
  748. }
  749.  
  750. void
  751. print_message_length(scb)
  752. struct pop_scb *scb;
  753. {
  754.     char *print_control_string;
  755.  
  756.     if (scb == NULLSCB)    /* check for null -- wa6smn */
  757.         return;
  758.     if (scb->msg_len > 0)
  759.         print_control_string = length_rsp;
  760.     else if (scb->msg_num <= scb->folder_len)
  761.         print_control_string = length_rsp;
  762.     else
  763.         print_control_string = no_more_rsp;
  764.  
  765.     (void)usprintf(scb->socket,print_control_string,scb->msg_len,scb->msg_num);
  766. }
  767.